11 Docker 基础 - 容器网络互连
在 Docker 中,容器之间的网络互连是非常重要的,因为它允许不同的容器之间进行通信和数据交换。
默认情况下,所有容器都是以
bridge方式连接到 Docker 的一个虚拟网桥上。
Docker Network
bash
❯ ip addr # 查看主机网络信息
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 52:54:00:3e:47:20 brd ff:ff:ff:ff:ff:ff
altname enp0s5
altname ens5
inet 10.0.16.3/22 metric 100 brd 10.0.19.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe3e:4720/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:e8:29:8e:92 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:e8ff:fe29:8e92/64 scope link
valid_lft forever preferred_lft forever
5: veth5077d5d@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 2e:17:e8:34:a9:f6 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::2c17:e8ff:fe34:a9f6/64 scope link
valid_lft forever preferred_lft forever
❯ docker run -d \
--name nginx \
-p 80:80 \
nginx # 启动一个 nginx 容器
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
1f7ce2fa46ab: Pull complete
9b16c94bb686: Pull complete
9a59d19f9c5b: Pull complete
9ea27b074f71: Pull complete
c6edf33e2524: Pull complete
84b1ff10387b: Pull complete
517357831967: Pull complete
Digest: sha256:e5c240a6604281581e9828af96485f7bcb9fce9e7b0e43b8189ea9f38495a4c9
Status: Downloaded newer image for nginx:latest
9c182ced195860db79c933385af4e9d03b727a3f5c34289b6b57c02e5d837c19
❯ dip nginx # 查看 nginx 容器的 IP
172.17.0.2
❯ docker run -d --name dockerfile-demo -p 8080:8080 demo:1.0 # 启动一个 dockerfile-demo 容器
6dfaae39e87c8c60167f97d15534022ba6c43c6828e864b576573bc17551623e
❯ dip dockerfile-demo # 查看 dockerfile-demo 容器的 IP
172.17.0.3
❯ dex dockerfile-demo ping 172.17.0.2 # 在 dockerfile-demo 容器中 ping nginx 容器
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.172 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.067 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.064 ms
64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.063 ms
^C
--- 172.17.0.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 81ms
rtt min/avg/max/mdev = 0.063/0.091/0.172/0.047 ms- 发现 nginx 容器和 dockerfile-demo 容器之间可以互联,没有问题。
- 但是,容器的网络 IP 其实是一个虚拟的 IP,其值并不固定与某一个容器绑定,如果我们在开发时写死某个 IP,而在部署时很可能 MySQL 容器的 IP 会发生变化,连接会失败。
- 所以,我们必须借助于 docker 的网络功能来解决这个问题。
常用命令
TIP
加入自定义网络的容器才可以通过容器名互相访问,否则只能通过 IP 访问。
| 命令 | 说明 | 文档地址 |
|---|---|---|
docker network create | 创建一个网络 | docker network create |
docker network ls | 查看所有网络 | docs.docker.com |
docker network rm | 删除指定网络 | docs.docker.com |
docker network prune | 清除未使用的网络 | docs.docker.com |
docker network connect | 使指定容器连接加入某网络 | docs.docker.com |
docker network disconnect | 使指定容器连接离开某网络 | docker network disconnect |
docker network inspect | 查看网络详细信息 | docker network inspect |
自定义网络演示
创建一个网络
bash
❯ docker network create hmall # 创建一个自定义网络 hmall
7a1c8ced3c4c3c337d37bb0ad8f093cf1b5df5491b0df6079e5b0eff13d20f05
❯ docker network ls # 查看所有网络,发现多了一个 hmall 网络
NETWORK ID NAME DRIVER SCOPE
d63a3b4e98da bridge bridge local
7a1c8ced3c4c hmall bridge local
425a483112a6 host host local
bbbc870dae7e none null local
❯ dkpsf -a # 查看所有容器
CONTAINER ID IMAGE PORTS STATUS NAMES
57c068845948 mysql 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp Up 49 seconds mysql
6dfaae39e87c demo:1.0 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp Up 11 minutes dockerfile-demo
9c182ced1958 nginx 0.0.0.0:80->80/tcp, :::80->80/tcp Up 17 minutes nginx- 通过
docker network create命令创建了一个自定义网络 hmall - 通过
docker network ls命令查看所有网络,发现多了一个 hmall 网络bridge网络:Docker 默认的网络。这是 Docker 安装后自动创建的网络,用于容器之间的通信。bridge网络是在单个 Docker 主机上的本地范围内运行的,通过 NAT(Network Address Translation)技术将容器内部的 IP 地址映射到主机上,使得容器可以访问外部网络。hmall网络:我们为特定应用或服务创建的自定义网络。它使用bridge驱动程序,因此与默认的bridge网络类似。host网络:它使用host驱动程序。与默认的bridge网络不同,host网络允许容器直接使用主机的网络命名空间,即它们共享主机的网络栈。这意味着容器可以直接使用主机的网络接口,不需要额外的端口映射。none网络:它使用null驱动程序。在none网络中,容器没有网络连接。这对于一些特殊的使用场景可能很有用,其中容器不需要网络连接,或者网络连接是通过其他手段设置的。
| 特点 | none 网络模式 | host 网络模式 | bridge 网络模式 |
|---|---|---|---|
| 网络连接 | 无网络连接,容器内无法直接访问外部网络 | 共享主机的网络命名空间,与主机网络一致 | 容器连接到默认的 Docker 创建的网桥 |
| IP 地址 | 未分配 IP 地址 | 与主机相同,共享主机的 IP 地址 | 在独立的网络命名空间中分配唯一的 IP 地址 |
| 访问外部网络 | 无法直接访问外部网络 | 直接访问主机网络,无需端口映射 | 通过 NAT 技术实现容器与外部网络的通信 |
| 适用场景 | 不需要网络连接的容器,独立运行的工具或任务 | 需要最大化性能和直接访问主机网络的应用 | 多个容器需要在同一主机上相互通信的场景 |
已运行的容器添加到自定义网路
bash
❯ dk network connect hmall mysql --alias db # 将 mysql 容器添加到 hmall 网络,并设置别名为 db
❯ dk network connect hmall dockerfile-demo --alias demo # 将 dockerfile-demo 容器添加到 hmall 网络,并设置别名为 demo
❯ dex dockerfile-demo ping db # 在 dockerfile-demo 容器中 ping db 容器,也就是 mysql 容器
PING db (172.18.0.2) 56(84) bytes of data.
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=1 ttl=64 time=0.143 ms
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=2 ttl=64 time=0.040 ms
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=3 ttl=64 time=0.060 ms
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=4 ttl=64 time=0.047 ms
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=5 ttl=64 time=0.063 ms
^C
--- db ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 67ms
rtt min/avg/max/mdev = 0.040/0.070/0.143/0.038 ms
❯ dex dockerfile-demo ping mysql # 使用容器名 mysql 也可以 ping 通
PING mysql (172.18.0.2) 56(84) bytes of data.
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=1 ttl=64 time=0.048 ms
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=2 ttl=64 time=0.061 ms
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=3 ttl=64 time=0.052 ms
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=4 ttl=64 time=0.064 ms
^C
--- mysql ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 52ms
rtt min/avg/max/mdev = 0.048/0.056/0.064/0.008 ms总结:
- 在自定义网络中,可以给容器起多个别名,默认的别名是容器名本身
- 在同一个自定义网络中的容器,可以通过别名互相访问
启动容器时添加到自定义网路
bash
❯ docker run -d --name nginx1 --network hmall nginx # 启动一个 nginx 容器,并添加到 hmall 网络
6b06b91c8787e9d9e1109acbeb281c8852847350bbbdb64106557dd00586a0ea
❯ dex dockerfile-demo ping nginx1 # 在 dockerfile-demo 容器中 ping nginx1 容器
PING nginx1 (172.18.0.4) 56(84) bytes of data.
64 bytes from nginx1.hmall (172.18.0.4): icmp_seq=1 ttl=64 time=0.111 ms
64 bytes from nginx1.hmall (172.18.0.4): icmp_seq=2 ttl=64 time=0.070 ms
64 bytes from nginx1.hmall (172.18.0.4): icmp_seq=3 ttl=64 time=0.068 ms
64 bytes from nginx1.hmall (172.18.0.4): icmp_seq=4 ttl=64 time=0.071 ms
^C
--- nginx1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 70ms
rtt min/avg/max/mdev = 0.068/0.080/0.111/0.017 ms
❯ dkNinc hmall # 查看 hmall 网络中的容器
57c0688459482dcc5ef9f87739a931aa2a070a8a20bf25409c082ac7cf8c5023: mysql
6b06b91c8787e9d9e1109acbeb281c8852847350bbbdb64106557dd00586a0ea: nginx1
6dfaae39e87c8c60167f97d15534022ba6c43c6828e864b576573bc17551623e: dockerfile-demo访问自定义网络外的容器
bash
❯ dkNinc hmall # 查看 hmall 网络中的容器
57c0688459482dcc5ef9f87739a931aa2a070a8a20bf25409c082ac7cf8c5023: mysql
6b06b91c8787e9d9e1109acbeb281c8852847350bbbdb64106557dd00586a0ea: nginx1
6dfaae39e87c8c60167f97d15534022ba6c43c6828e864b576573bc17551623e: dockerfile-demo
❯ dex dockerfile-demo ping nginx # 在 dockerfile-demo 容器中 ping nginx 容器,发现 ping 不通
ping: nginx: Name or service not known
❯ dk network connect hmall nginx # 将 nginx 容器添加到 hmall 网络
❯ dex dockerfile-demo ping nginx # 在 dockerfile-demo 容器中 ping nginx 容器,可以 ping 通了
PING nginx (172.18.0.5) 56(84) bytes of data.
64 bytes from nginx.hmall (172.18.0.5): icmp_seq=1 ttl=64 time=0.066 ms
64 bytes from nginx.hmall (172.18.0.5): icmp_seq=2 ttl=64 time=0.059 ms
64 bytes from nginx.hmall (172.18.0.5): icmp_seq=3 ttl=64 time=0.066 ms
^C
--- nginx ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 29ms
rtt min/avg/max/mdev = 0.059/0.063/0.066/0.009 ms
❯ dkNinc hmall # 查看 hmall 网络中的容器
57c0688459482dcc5ef9f87739a931aa2a070a8a20bf25409c082ac7cf8c5023: mysql
6b06b91c8787e9d9e1109acbeb281c8852847350bbbdb64106557dd00586a0ea: nginx1
6dfaae39e87c8c60167f97d15534022ba6c43c6828e864b576573bc17551623e: dockerfile-demo
9c182ced195860db79c933385af4e9d03b727a3f5c34289b6b57c02e5d837c19: nginxalias
bash
# 查看指定容器 ip
alias dip = docker inspect --format '\''{{ .NetworkSettings.IPAddress }}'\
# 进入容器
alias dex = docker exec -i -t
# 查看指定网络中的容器
dkNinc() {
docker network inspect -f '{{ range $key, $value := .Containers }}{{ printf "%s: %s\n" $key .Name}}{{ end }}' $1
}总结
- 在自定义网络中,可以给容器起多个别名,默认的别名是容器名本身
- 加入自定义网络的容器才可以通过容器名互相访问
docker network create创建一个自定义网络docker network connect将已经运行的容器添加到自定义网络docker run --network hmall将容器添加到自定义网络docker network disconnect将容器从自定义网络中移除docker network inspect查看网络详细信息docker network ls查看所有网络docker network rm删除指定网络docker network prune清除未使用的网络